作者:陈广
日期:2018-4-11
本想这个程序用 TypeScript 来实现的,但突然发现。只有两个事件方法,真没必要用 TypeScript。即使用了,代码也只多不少,因为 JavaScript 中的两个不同类型间是可以进行对比的。在需要用到类的地方我们再使用 TypeScript。学习之前先玩玩这个游戏:
拼图游戏和拼数字游戏其实是一样的,思路无任何不同,只是实现上稍有区别。这一次我们先将可移动的按钮在 HTML 中创建,之后再演示如何在 JavaScript 中拼凑 HTML,动态插入 Div 中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>拼数字游戏</title>
<link rel="stylesheet" href="NumberGame.css">
</head>
<body>
<div id="Container">
<img class="backgroundImg" src="img/1.png" onclick="Btn_Click(0)"/>
<img class="backgroundImg" src="img/2.png" onclick="Btn_Click(1)"/>
<img class="backgroundImg" src="img/3.png" onclick="Btn_Click(2)"/>
<img class="backgroundImg" src="img/4.png" onclick="Btn_Click(3)"/>
<img class="backgroundImg" src="img/5.png" onclick="Btn_Click(4)"/>
<img class="backgroundImg" src="img/6.png" onclick="Btn_Click(5)"/>
<img class="backgroundImg" src="img/7.png" onclick="Btn_Click(6)"/>
<img class="backgroundImg" src="img/8.png" onclick="Btn_Click(7)"/>
<img class="backgroundImg" src="img/9.png" onclick="Btn_Click(8)"/>
</div>
<button id="Button">开始游戏</button>
</body>
<script src="NumberGame.js"></script>
</html>
因为要存放图片,这里并没有使用按钮控件,而是直接使用img
。我们看到在Btn_Click
方法中加入了一个数字参数,主要用于方便在 JavaScript 中判断点击的是哪一个按钮。其实也可以不用加入这个参数,直接在src
属性里把相应数字提取出来进行判断。这里更多是为了演示如何在鼠标事件里传递参数。
body {
text-align: center;
background-color: #ddd;
}
#Container {
display: flex;
flex-wrap: wrap;
position: relative;
width: 240px;
height: 239px;
margin: 0 auto;
margin-top: 20px;
border: 5px solid darkgoldenrod;
border-radius: 5px;
}
.backgroundImg {
width: 80px;
height: 80px;
box-sizing: border-box;
border: 2px solid darkgoldenrod;
}
#Button {
margin-top: 20px;
padding: 10px 20px;
background: #A2B598;
background: -webkit-gradient(linear, left top, left bottom, from(#BDD1B4), to(#A2B598));
background: -moz-linear-gradient(-90deg, #BDD1B4, #A2B598);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#BDD1B4', EndColorStr='#A2B598');
}
#Button:hover {
background: #BDD1B4;
background: -webkit-gradient(linear, left top, left bottom, from(#A2B598), to(#BDD1B4));
background: -moz-linear-gradient(-90deg, #A2B598, #BDD1B4);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#A2B598', EndColorStr='#BDD1B4');
}
#Button:active {
background: #A2B598;
}
var imgList; //装按钮的数组
var cover = 0;
//窗体载入事件
window.onload = function () {
var container = document.getElementById("Container");
imgList = container.children;
//给开始游戏按钮绑定事件
document.getElementById("Button").addEventListener("click", PlayGame);
}
//随机函数low表示最小随机值,high表示最大随机值
function randomBetween(low, high) {
return Math.floor(Math.random() * (high - low + 1) + low);
}
//开始游戏方法,用于绑定开始游戏按钮
function PlayGame() {
console.log(cover);
imgList[cover].style.opacity = "1";
SetBorder("2");
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (var i = 0; i < 8; i++) {
var rmNum = randomBetween(i, 8);
var temp = nums[i];
nums[i] = nums[rmNum];
nums[rmNum] = temp;
}
for (var i = 0; i < 9; i++) {
imgList[i].src = "img/" + nums[i] + ".png";
}
cover = randomBetween(0, 8);
imgList[cover].style.opacity = "0";
}
//单击数字时的事件
function Btn_Click(index) {
if (((Math.abs(index - cover) == 1) &&
(Math.floor(index / 3) == Math.floor(cover / 3))) ||
(Math.abs(index - cover) == 3)) {
var temp = imgList[cover].src;
imgList[cover].src = imgList[index].src
imgList[index].src = temp;
imgList[cover].style.opacity = "1";
imgList[index].style.opacity = "0";
cover = index;
}
//判定是否游戏结束
for (var i = 0; i < 9; i++) {
var str = imgList[i].src;
if (str[str.length - 5] != i + 1) {
break;
}
if (i == 8) {
imgList[cover].style.opacity = "1";
SetBorder("0");
alert("闯关成功!");
}
}
}
//设置图片边框
function SetBorder(width) {
for (var i = 0; i < 9; i++) {
imgList[i].style.border = width + "px solid darkgoldenrod";
}
}
由于 div 的children
已经将 9 个按钮存放在数组中了,所以可以直接使用,无需另外创建数组存放。为此我还改了算法,改完后惊喜地发现,原来代码还可以更少。简而言之,之前使用的是二维数组实现,现在改用一维数组实现了。看来之前是思想是走弯路了。
对于这个游戏而言,以上实现其实是最完美的了。下面换一种方式来实现,同样的 HTML,用 JavaScript 动态插入。之所以要这样做,是因为这是实现目录树的关键。
将 HTML 改为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>拼数字游戏</title>
<link rel="stylesheet" href="NumberGame.css">
</head>
<body>
<div id="Container"></div>
<button id="Button">开始游戏</button>
</body>
<script src="NumberGame.js"></script>
</html>
现在看,HTML 代码少了很多,清爽了。
JavaScript 这边,只需更改window.onload
方法,其它不用动:
window.onload = function () {
var container = document.getElementById("Container");
var str = "";
for (var i = 0; i < 9; i++) {
str += '<img class="backgroundImg" src="img/' + (i + 1) +
'.png" onclick="Btn_Click(' + i + ')"/>'
}
container.innerHTML=str;
imgList = container.children;
//给开始游戏按钮绑定事件
document.getElementById("Button").addEventListener("click", PlayGame);
}
我们看到,这次通过一个循环将所有img
的 HTML 拼凑出来,然后通过innerHTML
属性注入到 div 中。效果和在 HTML 中写一模一样。
注入 HTML 的方法一下就写完了,比我想象的快多了。突然发现,目录树也不是那么难,惊喜啊!